#include "lua_config.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <utils/logger.h>
#include "lua_scada.h"
#include <vector>

namespace protocol {
LuaConfig::LuaConfig()
{
	luaScada_ = new LuaScada();
	auto scada = lua_.CreateUserdata<LuaScada>(luaScada_);
	scada.Bind("setProtocolName", &LuaScada::GetProtocolName);
	lua_.GetGlobalEnvironment().Set("scada", scada);
}

bool LuaConfig::LoadLuaFile(const std::string &protocolPath)
{
	std::ifstream luaFile(protocolPath);
	if (!luaFile.is_open()) {
		HTELINK_LOG_ERR("%s open failed", protocolPath.c_str());
		return false;
	}
	std::stringstream buffer;
	buffer << luaFile.rdbuf();
	std::string err = lua_.RunScript(std::string(buffer.str()));
	HTELINK_LOG_DEBUG(err.c_str());
	LuaTable global = lua_.GetGlobalEnvironment();
	LuaTable deviceList = global.Get<LuaTable>("deviceList");


	std::vector<dbms::Protocol_t> protocolList;
	deviceList.ForAllStringKeys(
		[&, this](std::string key, LuaType::Value value) {
			dbms::Protocol_t protocol;
			protocol.set_id(key);

			HTELINK_LOG_DEBUG("key: %s, type: %d", key.c_str(), value);
			if (value != LuaType::table) {
				return;
			}
			LuaTable device = deviceList.Get<LuaTable>(key);
			std::string name = GetName(device, "getName");
			// protocol.set_name();
			HTELINK_LOG_DEBUG("kk key: %s, type: %d, name: %s", key.c_str(),
				value, name.c_str());
			dbms::FuncParams_t *acquire = protocol.add_funcparams();
			*acquire = GetFuncpoint(device, "acquire");
			// dbms::FuncParams_t *ctrl = protocol.add_funcparams();
			dbms::FuncParams_t ctrl = GetFuncpoint(device, "ctrl");
			protocolList.push_back(protocol);
		});
	luaFile.close();
	return true;
}
std::string LuaConfig::GetName(LuaTable &table, const std::string &key)
{
	auto getFunc = table.Get<LuaFunction<void(int)> >(key);
	// if (!getFunc) {
	HTELINK_LOG_DEBUG("get key %s", key.c_str());
	// 	return "";
	// }
	std::string result;
	// luaScada_->SubscribeGetNameResult([&](std::string name) { result = name;
	// });
	// getFunc.Invoke(1);
	return result;
}
dbms::FuncParams_t LuaConfig::GetFuncpoint(
	LuaTable &table, const std::string &key)
{
	LuaType::Value type = table.GetTypeOfValueAt(key);
	if (type != LuaType::function) {
		HTELINK_LOG_DEBUG("get key %s, type: %d", key.c_str(), type);
		return dbms::FuncParams_t();
	}
	LuaTable funcTable = table.Get<LuaTable>(key);
	HTELINK_LOG_DEBUG("get key %s", key.c_str());
	funcTable.ForAllStringKeys([](std::string key, LuaType::Value v) {
		HTELINK_LOG_DEBUG("key: %s, type: %d", key.c_str(), key);
	});
	return dbms::FuncParams_t();
}
} // namespace protocol
